package br.com.mayco.controller;

import br.com.mayco.persistence.BaseDaoFactory;
import br.com.mayco.persistence.Dao;
import br.com.mayco.persistence.EntityDecorator;
import br.com.mayco.persistence.search.ListFilter;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.faces.event.ActionEvent;

/**
 * @author Mayco Lucian
 * @since 25/02/2013
 * @version 1.0.0
 */
public class CrudBean<T extends Serializable> extends BaseBean {

    private Dao<T> dao;
    private Class entityClass;
    protected T selected;
    private List<T> list;
    private Boolean autoCreateList;
    private Boolean autoUpdate;
    private Boolean autoCreateSelected;
    private Boolean showGenericMessages;
    private String pageView;
    private String pageInsert;

    //<editor-fold defaultstate="collapsed" desc="propriedades">
    public void setDao(Dao<T> dao) {
        this.dao = dao;
    }

    public Dao<T> getDao() {
        if (dao == null) {
            dao = BaseDaoFactory.createDao(entityClass);
        }
        return dao;
    }

    public void setEntityClass(Class entityClass) {
        this.entityClass = entityClass;
    }

    public Class getEntityClass() {
        return entityClass;
    }

    public T getSelected() {
        return selected;
    }

    public void setSelected(T selected) {
        this.selected = selected;
    }

    public List<T> getList() {
        if ((list == null && autoCreateList) || autoUpdate) {
            list = (List<T>) getDao().getAll();
        }
        return applyFilter(list);
    }

    public void setList(List<T> list) {
        this.list = list;
    }

    public Boolean getAutoCreateList() {
        return autoCreateList;
    }

    public void setAutoCreateList(Boolean autoCreateList) {
        this.autoCreateList = autoCreateList;
    }

    public void setAutoCreateSelected(Boolean autoCreateSelected) {
        this.autoCreateSelected = autoCreateSelected;
    }

    public Boolean getAutoCreateSelected() {
        return autoCreateSelected;
    }

    public Boolean getShowGenericMessages() {
        return showGenericMessages;
    }

    public void setShowGenericMessages(Boolean showGenericMessages) {
        this.showGenericMessages = showGenericMessages;
    }

    public String getPageInsert() {
        return pageInsert;
    }

    public void setPageInsert(String pageInsert) {
        this.pageInsert = pageInsert;
    }

    public String getPageView() {
        return pageView;
    }

    public void setPageView(String pageView) {
        this.pageView = pageView;
    }

    public Boolean getAutoUpdate() {
        return autoUpdate;
    }

    public void setAutoUpdate(Boolean autoUpdate) {
        this.autoUpdate = autoUpdate;
    }

    //</editor-fold>
    public CrudBean(Class entityClass) {
        autoCreateList = true;
        autoCreateSelected = true;
        showGenericMessages = true;
        this.entityClass = entityClass;
        dao = BaseDaoFactory.createDao(entityClass);
        autoUpdate = true;
    }

    public String cancelNavigation() {
        if (cancel(null)) {
            return pageView;
        }
        return null;
    }

    public String createNavigation() {
        if (insert(null)) {
            return pageInsert;
        }
        return null;
    }

    public String updateNavigation() {
        return pageInsert;
    }

    public String listNavigation() {
        return pageView;
    }

    public String saveNavigation() {
        if (save(null)) {
            return pageView;
        }
        return null;
    }

    public String removeNavigation() {
        if (remove(null)) {
            return pageView;
        }
        return null;
    }

    public boolean cancel(ActionEvent event) {
        selected = null;
        addMessage("Ação cancelada", WARN);
        return true;
    }

    public boolean insert(ActionEvent event) {
        boolean success = true;
        if (autoCreateSelected) {
            try {
                selected = (T) entityClass.newInstance();
            } catch (Exception ex) {
                getMessages().addError("Erro ao criar instancia da entidade");
                ex.printStackTrace();
                success = false;
            }
        }
        System.out.println("insert: " + success);
        return success;
    }

    public boolean save(ActionEvent event) {
        boolean success = false;
        if (selected == null) {
            addMessage("Não é possível gravar uma entidade vazia", ERROR);
            return success;
        }
        if (new EntityDecorator(selected).getPrimaryKey() == null) {
            boolean create = dao.create(selected);
            if (create) {
                addMessage("Dados gravados com sucesso", INFO);
                if (getList() != null) {
                    getList().add(selected);
                }
            } else {
                addMessage("Erro ao gravar dados", ERROR);
            }
            success = create;
        } else {
            boolean update = dao.update(selected);
            if (update) {
                addMessage("Dados alterados com sucesso", INFO);
            } else {
                addMessage("Erro ao alterar dados", ERROR);
            }
            success = update;
        }
        System.out.println("save: " + success);
        return success;
    }

    public boolean remove(ActionEvent event) {
        if (selected == null) {
            addMessage("Não é possível remover uma entidade vazia", ERROR);
            return false;
        }
        boolean delete = dao.delete(selected);
        if (delete) {
            addMessage("Dados removidos com sucesso", INFO);
            getList().remove(selected);
        } else {
            addMessage("Erro ao remover dados", ERROR);
        }
        return delete;
    }

    public List<T> applyFilter(List<T> listToFilter) {
        return listToFilter;
    }

    public List<T> applyListFilter(List<T> list, ListFilter<T> filter) {
        List<T> newList = new ArrayList<T>();
        for (T obj : list) {
            if (filter.applyFilter(obj)) {
                newList.add(obj);
            }
        }
        return newList;
    }
    //<editor-fold defaultstate="collapsed" desc="Mensagens">
    public final static int INFO = 4;
    public final static int WARN = 7;
    public final static int ERROR = 13;
    public final static int FATAL = 99;

    public void addMessage(String text, int type) {
        System.out.println("--CrudBean---------");
        System.out.println(text);
        System.out.println("___________________");
        if (showGenericMessages == false) {
            return;
        }
        switch (type) {
            case INFO:
                getMessages().addInfo(text);
                break;
            case ERROR:
                getMessages().addError(text);
                break;
            case WARN:
                getMessages().addWarn(text);
                break;
            case FATAL:
                getMessages().addFatal(text);
                break;
            default:
                break;
        }
    }
    //</editor-fold>
}
